package cn.itcast.com.MyStackByArray;

import java.util.EmptyStackException;

/**
 * Created by 郭浩 on 2020/8/18 20:23
 */
public class MyStack<E> {
    //初始顶部索引
    private int top = -1;
    //初始化数量
    private int size = 0;
    //初始容量
    private Integer DEFAULT_CAPACITY = 10;
    private Integer MAX_CAPACITY = Integer.MAX_VALUE - 8;

    private Object[] list;


    //构造方法，初始化


    public MyStack() {
        this.list = new Object[DEFAULT_CAPACITY];
    }
    public MyStack(int initialCapacity) {
        if (initialCapacity <= 0  || initialCapacity > MAX_CAPACITY ){
            throw new IllegalArgumentException("IllegalArgumentException initialCapacity = "+ initialCapacity);
        }
        this.list = new Object[initialCapacity];
    }

    //入栈,在栈顶添加元素
    public void push(E e){
        if (size == list.length){
            //扩容
            int newLength = calculateCapacity();
            grow(newLength);
        }else {
            top++;
            list[top] = e;
            size++;
        }
    }

    private void grow(int newLength) {
        E[] newArr = (E[]) new Object[newLength];
        for (int i = 0; i <= top; i++) {
            newArr[i] = (E) list[i];
        }
        list = newArr;
    }

    private int calculateCapacity() {
        if (list.length == MAX_CAPACITY) {
            throw new RuntimeException("Array is too large!");
        }
        int newLength = list.length + (list.length >> 1);
        if (newLength < 0 || newLength > MAX_CAPACITY) {
            newLength = MAX_CAPACITY;
        }
        return newLength;
    }

    //出栈。栈顶删除元素并弹出
    public E pop(){
        if (isEmpty()){
            throw new EmptyStackException();
        }
        E value = (E) list[top];
        top--;
        return value;
    }

    //    查看栈顶元素 (peek)：访问栈顶元素但不弹出，O(1)
    public E peek() {
        if (isEmpty()){
            throw new EmptyStackException();
        }
        return (E) list[top];
    }

    private boolean isEmpty() {
        return size == 0;
    }

    private Integer getSize(){
        return size;
    }

}
